/*
 * funcionesDisco.c
 *
 *  Created on: 27/09/2011
 *      Author: utn_so
 */

#include "funcionesDisco.h"

void agregarPeticionACola(t_peticion* peticion){
	t_config *config = getConfig();
	insertarEnDiscoOrdenado(peticion, config->algoritmoPlanificacion);
}

void insertarEnDiscoOrdenado(t_peticion *peticion, int algoritmo){

	t_chs *posActual = getCHSActual();
	t_list *list = NULL;
	int index = 0;
	if (algoritmo == CSCAN){
		if (posActual->sector < peticion->nSector){
			list = getListCargaPeticiones(algoritmo, ASCENDENTE);
			index = insertarOrdenadoAscendente(list, peticion->nSector);
			collection_list_put(list,index, peticion);
		}
		else{
			list = getListCargaPeticiones(algoritmo, DESCENDENTE);
			index = insertarOrdenadoDescendente(list, peticion->nSector);
			collection_list_put(list,index, peticion);
		}
	}
	else if (algoritmo == FSCAN){

		list = getListCargaPeticiones(algoritmo,0);
		index = insertarOrdenadoAscendente(list, peticion->nSector);
		collection_list_put(list, index, peticion);
	}
}

int insertarOrdenadoAscendente(t_list *lista, int sector){

	t_config *config = getConfig();
	if (lista == NULL){
		logMessage(LOG_DEBUG,"agrege peticion q hace referencia al ultimo sector del disco %l",config->sectores-1);
		t_peticion *peticion = inicializaPeticion(config->sectores -1);
		collection_list_add(lista,peticion);
	}
	int sizeLista = collection_list_size(lista);
	int index = 0;
	t_peticion *pet;
	while (index <= sizeLista){
		pet = collection_list_get(lista,index);
		if (pet->nSector <= sector){
			index++;
		}
		else
			return index;
	}
	return index;
}

int insertarOrdenadoDescendente(t_list *lista, int sector){

	t_config *config = getConfig();
	if (lista == NULL){
		logMessage(LOG_DEBUG,"agrege peticion q hace referencia al ultimo sector del disco %l",config->sectores-1);
		t_peticion *peticion = inicializaPeticion(0);
		collection_list_add(lista,peticion);
	}

	int sizeLista = collection_list_size(lista);
	int index = 0;
	t_peticion *pet;
	while (index <= sizeLista){
		pet = collection_list_get(lista,index);
		if (pet->nSector >= sector){
			index++;
		}
		else
			return index;
	}
	return index;
}

t_peticion *tomarSiguientePeticion(int algoritmo){

	t_config *config = getConfig();
	t_peticion *peticion = NULL;
	int index = 0;

	if (algoritmo == FSCAN){

		t_list *listaPet = getListPeticiones(algoritmo);
		if (collection_list_size(listaPet) == 0){
			switchListaPeticionFSCAN();
		}

		listaPet = getListPeticiones(algoritmo);
		peticion = (t_peticion*)collection_list_remove(listaPet,0);
		if (peticion == NULL){
			logMessage(LOG_INFO,"No hay peticiones a atender WTF???");
		}

	}else if ( algoritmo == CSCAN)	{

		t_list *listaPet = getListPeticiones(algoritmo);
		if (collection_list_size(listaPet) == 0){
			switchListaPeticionCSCAN();
		}

		listaPet = getListPeticiones(algoritmo);
		peticion = (t_peticion*)collection_list_remove(listaPet,0);
		if (peticion == NULL){
			logMessage(LOG_INFO,"No hay peticiones a atender WTF???");
		}
	}
	return peticion;
}


void switchListaPeticionFSCAN(){

	t_listaAtencion *listAte = listaAtencion();
	t_listaAtencion *listEnEscu = listaAEscucha();

	listEnEscu->antencion = 1;
	listAte->antencion = 0;
}

void switchListaPeticionCSCAN(){

	t_listaAtencion *listASC = listaAscendente();
	t_listaAtencion *listDESC = listaDescendente();

	if (listASC->antencion == 1){
		listASC->antencion = 0;
		listDESC->antencion = 1;
	}
	else{
		listASC->antencion = 1;
		listDESC->antencion = 0;
	}

}

char * resolverTrace(t_peticion * peticion,int fd){
	t_chs *dirFisActual, *dirFisicaSolicitada, *proximoSector;
	t_config * config = getConfig();
	char *msj = (char *) malloc(100), *recorrido = (char *) malloc(100/2); /* Lo hice dividido 2 ya que el recv en la consola es de 100 */
	char *tiempoConsumido = (char *) malloc(sizeof(int)), *proxSector = (char *) malloc(sizeof(t_chs));
	int corte = 1, sentido;
	uint32_t cilindrosRecorridos = 0, sectoresRecorridos = 0;

	dirFisActual = getCHSActual();
	dirFisicaSolicitada = obtenerCHS(peticion->nSector);

	/* Creo la cabecera del msj a enviarle a la consola */
	sprintf(msj,"t|%d:%d|%d:%d|",dirFisActual->cilindro,dirFisActual->sector,dirFisicaSolicitada->cilindro,dirFisicaSolicitada->sector);
	while (corte){
		if (config->algoritmoPlanificacion == CSCAN){

			if (dirFisicaSolicitada->cilindro == dirFisActual->cilindro) {
				corte = 0;
			}else if (dirFisActual->cilindro == config->cilindros){
				dirFisActual->cilindro = 0;
				cilindrosRecorridos ++;
				sprintf(recorrido,"%d:%d,",dirFisActual->cilindro,dirFisActual->sector);
				strcat(msj,recorrido);
			}else if (dirFisActual->cilindro < config->cilindros){
				dirFisActual->cilindro ++;
				cilindrosRecorridos ++;
				sprintf(recorrido,"%d:%d,",dirFisActual->cilindro,dirFisActual->sector);
				strcat(msj,recorrido);
			}

		 }else{

			if (dirFisicaSolicitada->cilindro == dirFisActual->cilindro) {
				corte = 0;
			}else if ((dirFisActual->cilindro == config->cilindros) || (sentido == DOWN)){
				dirFisActual->cilindro --;
				cilindrosRecorridos ++;
				sentido = DOWN;
				sprintf(recorrido,"%d:%d,",dirFisActual->cilindro,dirFisActual->sector);
				strcat(msj,recorrido);
			}else if ((dirFisActual->cilindro == 0) || (sentido == UP)){
				dirFisActual->cilindro ++;
				cilindrosRecorridos ++;
				sentido = UP;
				sprintf(recorrido,"%d:%d,",dirFisActual->cilindro,dirFisActual->sector);
				strcat(msj,recorrido);
			}

		 }
	}

	corte = 1;

	while (corte){
		if (dirFisicaSolicitada->sector == dirFisActual->sector) {
			corte = 0;
		}else if (dirFisActual->sector == config->sectores){
			dirFisActual->sector = 0;
			sectoresRecorridos ++;
			sprintf(recorrido,"%d:%d,",dirFisActual->cilindro,dirFisActual->sector);
			strcat(msj,recorrido);
		}else if (dirFisActual->sector < config->sectores){
			dirFisActual->sector ++;
			sectoresRecorridos ++;
			sprintf(recorrido,"%d:%d,",dirFisActual->cilindro,dirFisActual->sector);
			strcat(msj,recorrido);
		}
	}

	free(recorrido);

	sprintf (tiempoConsumido,"|%d", (config->tiempoSaltoPistas * cilindrosRecorridos) + ((config->RPM/config->sectores) * sectoresRecorridos));
	strcat(msj,tiempoConsumido);
	free(tiempoConsumido);

	proximoSector = actualizarCHS(dirFisActual,1);/* TODO ver tema del proximo sector */
	sprintf(proxSector,"%d:%d",proximoSector->cilindro,proximoSector->sector);
	strcat(msj,proxSector);
	free(proxSector);

	setCHSActual(dirFisActual); /* Seteo CHS donde quedo despues de atender la peticion del TRACE */
	return msj;
}
